#!/usr/bin/env bash

set -e

source $(dirname $0)/cmdTestsCommon.inc.sh

# check that benchmarks can run
"$SBT" "scala3-bench/jmh:run 1 1 tests/pos/alias.scala"
# The above is here as it relies on the bootstrapped library.
"$SBT" "scala3-bench-bootstrapped/jmh:run 1 1 tests/pos/alias.scala"
"$SBT" "scala3-bench-bootstrapped/jmh:run 1 1 -with-compiler compiler/src/dotty/tools/dotc/core/Types.scala"

echo "testing scala.quoted.Expr.run from sbt scala"
"$SBT" ";scala3-compiler-bootstrapped/scalac -with-compiler tests/run-staging/quote-run.scala; scala3-compiler-bootstrapped/scala -with-compiler Test" > "$tmp"
grep -qe "val a: scala.Int = 3" "$tmp"


# setup for `scalac`/`scala` script tests
"$SBT" dist/pack

# check that `scalac` compiles and `scala` runs it
echo "testing ./bin/scalac and ./bin/scala"
clear_out "$OUT"
./bin/scalac "$SOURCE" -d "$OUT"
./bin/scala -classpath "$OUT" "$MAIN" > "$tmp"
test "$EXPECTED_OUTPUT" = "$(cat "$tmp")"

# Test scaladoc based on compiled classes
./bin/scaladoc -project Staging -d "$OUT1" "$OUT"
clear_out "$OUT1"

# check that `scalac` and `scala` works for staging
clear_out "$OUT"
./bin/scalac tests/run-staging/i4044f.scala -d "$OUT"
./bin/scala -with-compiler -classpath "$OUT" Test > "$tmp"

# check that `scalac -from-tasty` compiles and `scala` runs it
echo "testing ./bin/scalac -from-tasty and scala -classpath"
clear_out "$OUT1"
./bin/scalac "$SOURCE" -d "$OUT"
./bin/scalac -from-tasty -d "$OUT1" "$OUT/$TASTY"
./bin/scala -classpath "$OUT1" "$MAIN" > "$tmp"
test "$EXPECTED_OUTPUT" = "$(cat "$tmp")"

# check that `sbt scalac -decompile` runs
echo "testing sbt scalac -decompile from file"
./bin/scalac -decompile -color:never "$OUT/$TASTY" > "$tmp"
grep -qe "def main(args: scala.Array\[scala.Predef.String\]): scala.Unit =" "$tmp"

# check that `sbt scalac -print-tasty` runs
echo "testing sbt scalac -print-tasty from file"
./bin/scalac -print-tasty -color:never "$OUT/$TASTY" > "$tmp"
grep -qe "118:           STRINGconst 32 \[hello world\]" "$tmp"

echo "testing loading tasty from .tasty file in jar"
clear_out "$OUT"
./bin/scalac -d "$OUT/out.jar" "$SOURCE"
./bin/scalac -decompile -color:never "$OUT/out.jar" > "$tmp"
grep -qe "def main(args: scala.Array\[scala.Predef.String\]): scala.Unit =" "$tmp"

echo "testing printing tasty from .tasty file in jar"
./bin/scalac -print-tasty -color:never "$OUT/out.jar" > "$tmp"
grep -qe "118:           STRINGconst 32 \[hello world\]" "$tmp"

echo "testing -script from scalac"
clear_out "$OUT"
./bin/scalac -script "$SOURCE" > "$tmp"
test "$EXPECTED_OUTPUT" = "$(cat "$tmp")"

echo "testing sbt scalac with suspension"
clear_out "$OUT"
"$SBT" "scala3-compiler-bootstrapped/scalac -d $OUT tests/pos-macros/macros-in-same-project-1/Bar.scala tests/pos-macros/macros-in-same-project-1/Foo.scala"  > "$tmp"

# echo ":quit" | ./dist/target/pack/bin/scala  # not supported by CI

echo "testing ./bin/scaladoc"
clear_out "$OUT1"
./bin/scaladoc -project Hello -d "$OUT1" "$OUT/out.jar"

# check compilation when the class/tasty files already exist in the current directory
echo "testing i11644"
cwd=$(pwd)
clear_out "$OUT"
(cd "$OUT" && "$cwd/bin/scalac" "$cwd/tests/pos/i11644.scala" && "$cwd/bin/scalac" "$cwd/tests/pos/i11644.scala")

# check options specified in files
./bin/scalac @project/scripts/options "$SOURCE"

# test command line options
./bin/scalac -help > "$tmp" 2>&1
grep -qe "Usage: scalac <options> <source files>" "$tmp"

./bin/scala -help > "$tmp" 2>&1
grep -qe "Usage: scala <options> <source files>" "$tmp"

./bin/scala -d hello.jar tests/run/hello.scala
ls hello.jar

echo "testing i12973"
clear_out "$OUT"
./bin/scalac -d "$OUT/out.jar" tests/pos/i12973.scala
echo "Bug12973().check" | TERM=dumb ./bin/scala -cp "$OUT/out.jar" > "$tmp" 2>&1
grep -qe "Bug12973 is fixed" "$tmp"

echo "capturing scala version from dist/target/pack/VERSION"
cwd=$(pwd)
IFS=':=' read -ra versionProps < "$cwd/dist/target/pack/VERSION" # temporarily set IFS to ':=' to split versionProps
[ ${#versionProps[@]} -eq 3 ] && \
  [ ${versionProps[0]} = "version" ] && \
  [ -n ${versionProps[2]} ] || die "Expected non-empty 'version' property in $cwd/dist/target/pack/VERSION"
scala_version=${versionProps[2]}

echo "testing -sourcepath with incremental compile: inlining changed inline def into a def"
# Here we will test that a changed inline method symbol loaded from the sourcepath (-sourcepath compiler option)
# will have its `defTree` correctly set when its method body is required for inlining.
# So far I have not found a way to replicate issue https://github.com/lampepfl/dotty/issues/13994
# with sbt scripted tests, if a way is found, move this test there.
cwd=$(pwd)
sbt_test_command="++${scala_version}!;clean;prepareSources;compile;copyChanges;compile"
(cd "$cwd/tests/cmdTest-sbt-tests/sourcepath-with-inline" && "$SBT" "$sbt_test_command")
rm -rf "$cwd/tests/cmdTest-sbt-tests/sourcepath-with-inline/target"
rm -rf "$cwd/tests/cmdTest-sbt-tests/sourcepath-with-inline/project/target"
rm -f "$cwd/tests/cmdTest-sbt-tests/sourcepath-with-inline/src/main/scala/a/zz.scala"

echo "testing -sourcepath with incremental compile: hashing reference to changed inline def from an inline def"
# Here we will test that a changed inline method symbol loaded from the sourcepath (-sourcepath compiler option)
# will have its `defTree` correctly set when its method body is hashed by extractAPI, when referenced from another
# inline method.
# So far I have not found a way to replicate https://github.com/lampepfl/dotty/pull/12931#discussion_r753212124
# with sbt scripted tests, if a way is found, move this test there.
cwd=$(pwd)
sbt_test_dir="$cwd/tests/cmdTest-sbt-tests/sourcepath-with-inline-api-hash"
sbt_test_command="++${scala_version}!;clean;prepareSources;compile;copyChanges;compile"
(cd "$sbt_test_dir" && "$SBT" "$sbt_test_command")
rm -rf "$sbt_test_dir/target"
rm -rf "$sbt_test_dir/project/target"
rm -f "$sbt_test_dir/src/main/scala/a/zz.scala"
